package cn.iocoder.yudao.module.promotion.seckill.convert;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.api.product.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.api.promotion.activity.enums.PromotionTypeEnum;
import cn.iocoder.yudao.module.api.promotion.seckill.dto.SeckillValidateJoinRespDTO;
import cn.iocoder.yudao.module.promotion.activity.convert.ActivityConvert;
import cn.iocoder.yudao.module.promotion.seckill.dal.dataobject.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.seckill.dal.dataobject.SeckillProductDO;
import cn.iocoder.yudao.module.promotion.seckill.vo.*;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;

/**
 * 秒杀活动 Convert
 *
 * @author 芋道源码
 */
@Mapper
public interface SeckillActivityConvert {

    SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);

    SeckillActivityDO convert(SeckillActivityCreateReqVO bean);

    SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);

    SeckillActivityRespVO convert(SeckillActivityDO bean);

    List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list);

    AppSeckillActivityProductRespVO convert(SeckillProductDO bean);

    PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);

    default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page,
                                                          List<SeckillProductDO> seckillProducts,
                                                          List<ProductSpuRespDTO> spuList) {
        PageResult<SeckillActivityRespVO> pageResult = convertPage(page);
        // 拼接产品
        Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId);
        Map<Long, List<SeckillProductDO>> productMap = convertMultiMap(seckillProducts, SeckillProductDO::getActivityId);
        pageResult.getList().forEach(activity -> {
            activity.setProducts(convertList2(productMap.get(activity.getId())));
            MapUtils.findAndThen(spuMap, activity.getSpuId(),
                    spu -> {
                        activity.setSpuName(spu.getName());
                        activity.setPicUrl(spu.getPicUrl());
                        activity.setPrice(spu.getPrice());
                    });
        });
        return pageResult;
    }

    SeckillActivityDetailRespVO convert1(SeckillActivityDO activity);

    default SeckillActivityDetailRespVO convert(SeckillActivityDO activity, List<SeckillProductDO> products) {
        SeckillActivityDetailRespVO respVO = convert1(activity);
        respVO.setProducts(convertList2(products));
        return respVO;
    }

    @Mappings({
            @Mapping(target = "shopId", source = "activity.shopId"),
            @Mapping(target = "activityId", source = "activity.id"),
            @Mapping(target = "configIds", source = "activity.configIds"),
            @Mapping(target = "spuId", source = "activity.spuId"),
            @Mapping(target = "skuId", source = "product.skuId"),
            @Mapping(target = "seckillPrice", source = "product.seckillPrice"),
            @Mapping(target = "stock", source = "product.stock"),
    })
    SeckillProductDO convert(SeckillActivityDO activity, SeckillProductBaseVO product);

    default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activity) {
        return CollectionUtils.convertList(products, item -> convert(activity, item));
    }

    default List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list,
                                                    List<SeckillProductDO> productList,
                                                    List<ProductSpuRespDTO> spuList) {
        List<SeckillActivityRespVO> activityList = BeanUtils.toBean(list, SeckillActivityRespVO.class);
        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
        Map<Long, List<SeckillProductDO>> productMap = convertMultiMap(productList, SeckillProductDO::getActivityId);
        return CollectionUtils.convertList(activityList, item -> {
            // 设置 product 信息
            item.setSeckillPrice(getMinValue(productMap.get(item.getId()), SeckillProductDO::getSeckillPrice));
            // 设置 SPU 信息
            findAndThen(spuMap, item.getSpuId(), spu -> {
                item.setSpuName(spu.getName());
                item.setPicUrl(spu.getPicUrl());
                item.setPrice(spu.getPrice());
            });
            return item;
        });
    }

    default List<AppSeckillActivityProductRespVO> convertAppList(List<SeckillProductDO> productList, List<SeckillActivityDO> activityList, List<ProductSpuRespDTO> spuList, List<ProductSkuRespDTO> skuList) {
        List<AppSeckillActivityProductRespVO> list = new ArrayList<>(productList.size());
        Map<Long, SeckillActivityDO> activityMap = convertMap(activityList, SeckillActivityDO::getId);
        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
        Map<Long, ProductSkuRespDTO> skuMap = convertMap(skuList, ProductSkuRespDTO::getId);
        for (SeckillProductDO productDO : productList) {
            AppSeckillActivityProductRespVO respVO = convert(productDO);
            SeckillActivityDO activityDO = activityMap.get(productDO.getActivityId());
            respVO.setActivity(ActivityConvert.INSTANCE.convert(activityDO, PromotionTypeEnum.SECKILL_ACTIVITY.getValue()));
            respVO.setTotalLimitCount(activityDO.getTotalLimitCount());
            respVO.setSingleLimitCount(activityDO.getSingleLimitCount());
            respVO.setTotalStock(activityDO.getStock());
            ProductSpuRespDTO spuRespDTO = spuMap.get(productDO.getSpuId());
            ProductSkuRespDTO skuRespDTO = skuMap.get(productDO.getSkuId());
            ActivityConvert.INSTANCE.convert(respVO, spuRespDTO, skuRespDTO);
            list.add(respVO);
        }
        return list;
    }

    List<SeckillProductRespVO> convertList2(List<SeckillProductDO> list);

    List<AppSeckillActivityProductRespVO> convertList3(List<SeckillActivityDO> activityList);

    PageResult<AppSeckillActivityProductRespVO> convertPage1(PageResult<SeckillActivityDO> pageResult);

    AppSeckillActivityDetailRespVO convert2(SeckillActivityDO seckillActivity);

    SeckillValidateJoinRespDTO convert02(SeckillActivityDO activity, SeckillProductDO product);

}
